﻿
/*============== simpleIRC - http://matthias.van-eeghem.com/ ==============*
 *                                                                         *
 *  File: Commands.cs                                                      *
 *  Project: simpleIRC                                                     *
 *  Author(s): Matthias Van Eeghem <matthias@van-eeghem.com>               *
 *                                                                         *
 * ========================================================================*
 *                                                                         *
 *  This program is free software: you can redistribute it and/or modify   *
 *  it under the terms of the GNU General Public License as published by   *
 *  the Free Software Foundation, either version 3 of the License, or      *
 *  (at your option) any later version.                                    *
 *                                                                         *
 *  This program is distributed in the hope that it will be useful,        *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
 *  GNU General Public License for more details.                           *
 *                                                                         *
 *  You should have received a copy of the GNU General Public License      *
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                         *
===========================================================================*/

using System;
using System.Linq;

namespace simpleIRC.UI
{
    /// <summary>
    /// This class handles all command related functions of the application.
    /// </summary>

    public class Command
    {
        // This property will hold the reference to the class objects.
        private UserInterface UserInterface = null;
        private MainWindow mainWindow = null;

        /// <summary>
        ///  The constructor of the Command class.
        /// </summary>
        public Command(MainWindow parentWindow)
        {
            mainWindow = parentWindow;
            UserInterface = parentWindow.UserInterface;
        }

        /// <summary>
        /// This function handles all the commands used in the application.
        /// </summary>
        /// <param name="commandLine">The entire command including the / character and parameters</param>

        public void Handle(string commandLine)
        {
            string[] Parameters = commandLine.Split(new Char[] { ' ' });
            commandLine = commandLine.ToLower();

            if (commandLine.StartsWith("/join") || commandLine.StartsWith("/j"))
            {
                if(Parameters.Count() > 1)
                {
                    string Password = (Parameters.Count() > 2) ? Parameters[2] : "";
                    CommandJoin(Parameters[1], Password);
                }
            }

            else if (commandLine.StartsWith("/part") || commandLine.StartsWith("/p"))
            {
                Parameters = commandLine.Split(new Char[] { ' ' }, 3);

                string Channel = (Parameters.Count() > 1) ? Parameters[1] : "";
                string Reason = (Parameters.Count() > 2) ? Parameters[2] : "";
                CommandPart(Channel, Reason);
            }

            else if (commandLine.StartsWith("/quit") || commandLine.StartsWith("/q"))
            {
                Parameters = commandLine.Split(new Char[] { ' ' }, 2);
                string Reason = (Parameters.Count() > 1) ? Parameters[1] : "";
                CommandQuit(Reason);
            }

            else if(commandLine.StartsWith("/server") || commandLine.StartsWith("/s"))
            {
                if (Parameters.Count() > 1)
                {
                    Parameters = commandLine.Split(new Char[] { ' ' }, 3);
                    string hostName = (Parameters.Count() > 2) ? Parameters[2] : "";
                    CommandServer(Parameters[1], hostName);
                }
            }

            else if (commandLine.StartsWith("/whois"))
            {
                if (Parameters.Count() > 1)
                {
                    CommandWhois(Parameters[1]);
                }
            }
        }

        /// <summary>
        /// This command sends the WHOIS command to the server, and the server replies back with the user info.
        /// </summary>
        /// <param name="targetName">The user to get the information from</param>

        private void CommandWhois(string targetName)
        {
            if (mainWindow.CurrentServerWindow != -1 && Core.ServerList[mainWindow.CurrentServerWindow].ConnectionState == Core.eConnectionStates.Connected)
            {
                Core.ServerList[mainWindow.CurrentServerWindow].SendData("WHOIS " + targetName);
            }
        }

        /// <summary>
        /// This command allows a user to join a channel.
        /// </summary>
        /// <param name="channel">The channel to join</param>
        /// <param name="password">The (optional) password</param>
        
        private void CommandJoin(string channel, string password = "")
        {
            if (mainWindow.CurrentServerWindow != -1 && Core.ServerList[mainWindow.CurrentServerWindow].ConnectionState == Core.eConnectionStates.Connected)
            {
                Channel Channel = Core.GetChannelObject(channel, mainWindow.CurrentServerWindow);

                // Check if the user already joined that channel.
                if(Channel == null)
                {
                    new Channel(mainWindow.CurrentServerWindow, channel, password).Join();
                    new ChannelWindow(channel, mainWindow.CurrentServerWindow, (Core.ChannelList.Count - 1), mainWindow).Create();
                }
                else ChannelWindow.List[Channel.Index].ChannelTreeViewItem.IsSelected = true;
            }
        }

        /// <summary>
        /// The part command parts a channel with an optional reason
        /// </summary>
        /// <param name="channel">The channel to part</param>
        /// <param name="reason">The optional reason to send when parting</param>

        private void CommandPart(string channel, string reason)
        {
            // Check if there are parameters.
            if (mainWindow.CurrentServerWindow != -1 && Core.ServerList[mainWindow.CurrentServerWindow].ConnectionState == Core.eConnectionStates.Connected)
            {
                if (channel == "" && mainWindow.CurrentChannelWindow != -1) channel = Core.ChannelList[mainWindow.CurrentServerWindow].Name;

                Channel Channel = Core.GetChannelObject(channel, mainWindow.CurrentServerWindow);

                // Check if he already joined that channel.
                if (Channel != null)
                {
                    // Create the channel window.
                    ChannelWindow.List[Channel.Index].Remove();
                    Core.ChannelList[Channel.Index].Part(reason);
                }
            }
        }

        /// <summary>
        /// This command allows a user to connect to another server
        /// </summary>
        /// <param name="joinOption">The joinOptions, -n means new server window, no valid option passed means the client connects to the first parameter as hostname</param>
        /// <param name="hostName">The hostname to connect to (none if there wasn't a valid joinOption passed on)</param>

        private void CommandServer(string joinOption, string hostName)
        {
            int Port = 6667, ServerIndex = -1;
            string Nick = "irc_client0";
            string OptionalName = "irc_client1";
            string User = "kaboem";
            string PersonalText = "Hallo";

            Server Server = null;

            // If we already connected to a server, use the connect data from that server
            if(Core.ServerList.Count != 0)
            {
                ServerIndex = mainWindow.CurrentServerWindow;
                Server = Core.ServerList[ServerIndex];
                
                Port = Server.Port;
                Nick = Server.Nick;
                User = Server.UserName;
                OptionalName = Server.OptionalName;
                PersonalText = Server.PersonalText;
            }

            // -n means new server window, 
            if (joinOption == "-n")
            {
                // Create a new Server object
                Server NewServer = new Server(hostName, Port, Nick, User, OptionalName, PersonalText);

                new ServerWindow(hostName, (Core.ServerList.Count - 1), mainWindow).Create();
                NewServer.Connect();
            }

            else
            {
                hostName = joinOption;

                if (Core.ServerList.Count == 0)
                {
                    Server NewServer = new Server(hostName, Port, Nick, User, OptionalName, PersonalText);

                    new ServerWindow(hostName, (Core.ServerList.Count - 1), mainWindow).Create();
                    NewServer.Connect();
                }
                else
                {
                    // Disconnect from the old server, change the server name, reconnect
                    Server.Disconnect();
                    Server.Hostname = hostName;
                    Server.Connect();

                    // Change the visual header for the treeviewitem
                    ServerWindow.List[ServerIndex].ServerTreeViewItem.Header = hostName;
                }
            }
        }

        /// <summary>
        /// The quit command. This command disconnects the client from the server.
        /// </summary>
        /// <param name="reason">The quit reason</param>

        private void CommandQuit(string reason)
        {
            Server Server = Core.ServerList[mainWindow.CurrentServerWindow];

            // Check if there are parameters.
            if (reason != "")
            {
                Core.ServerList[mainWindow.CurrentServerWindow].Disconnect(reason, true);
            }
            else
            {
                // No quit message, just send the nick
                Core.ServerList[mainWindow.CurrentServerWindow].Disconnect(Server.Nick, true);
            }
        }
    }
}
